package controller;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JOptionPane;

import model.ArrayQueue;
import model.ArrayStack;
import model.QueuePredict;
import model.StackPredict;

public class DrawEventListener extends MouseAdapter implements MouseListener{
	
	private StackPredict<String> stack;
	private QueuePredict<String> queue;
	private ArrayStack<String> arrayStack;
	private ArrayQueue<String> arrayQueue;
	private String status;
	public enum modeOptions {ADDPREDICT, REMOVEPREDICT, WAITING}
	private modeOptions currentMode;
	private boolean paint = false;
	private boolean wasRemoved = false;
	private boolean wasNotRemoved = false;
	private boolean wasAdded = false;
	private boolean wasNotAdded = false;
	private String input = "";
	private String removed = "";

	public void updateStack(StackPredict<String> stack){

		this.stack = stack;
	}
	
	public void updateQueue(QueuePredict<String> queue){
		this.queue = queue;
	}
	
	public void updateArrayStack(ArrayStack<String> arrayStack){
		this.arrayStack = arrayStack;
	}
	
	public void updateArrayQueue(ArrayQueue<String> arrayQueue){
		this.arrayQueue = arrayQueue;
	}
	
	public void setPreidctionMode(modeOptions b) {
		currentMode = b;
	}
	
	public void updateStatus(String s){
		status = s;
	}
	
	public void updateElements(){
		stack = new StackPredict<String>();
		queue = new QueuePredict<String>();
		arrayQueue = new ArrayQueue<String>();
		arrayStack = new ArrayStack<String>();
	}
	
	public StackPredict<String> getStack(){
		return stack;
	}
	
	public QueuePredict<String> getQueue() {
		return queue;
	}
	
	
	public boolean shouldPaint(){
		return paint;
	}
	
	public void setInput(String s){
		input = s.substring(0, 1);
	}
	public String getRemoved(){
		return removed;
	}

	public void mouseClicked(MouseEvent e) {

		switch(currentMode){
		case ADDPREDICT:
			if(status.equals("STACK")){
				stackAddPredict(e.getX(), e.getY());
				currentMode = modeOptions.WAITING;
			}
			if(status.equals("QUEUE")){
				queueAddPredict(e.getX(), e.getY());
				currentMode = modeOptions.WAITING;
			}
			if(status.equals("ARRAYSTACK")){
				arrayStackAddPredict(e.getX(), e.getY());
			}
			if(status.equals("ARRAYQUEUE")){
				arrayQueueAddPredict(e.getX(), e.getY());
			}

			break;
		case REMOVEPREDICT:
			wasNotRemoved = true;	
			if(status.equals("STACK")){
				stackRemovePredict(e.getX(), e.getY());
				currentMode = modeOptions.WAITING;
			}
			if(status.equals("QUEUE")){
				queueRemovePredict(e.getX(), e.getY());
				currentMode = modeOptions.WAITING;
			}
			if(status.equals("ARRAYSTACK")){
				arrayStackRemovePredict(e.getX(), e.getY());
				currentMode = modeOptions.WAITING;
			}
			if(status.equals("ARRAYQUEUE")){
				arrayQueueRemovePredict(e.getX(), e.getY());
				currentMode = modeOptions.WAITING;
			}
			
			break;
		}	
	}
	
	private void arrayQueueRemovePredict(int x, int y) {
		
		ArrayList<Integer> xCo = arrayQueue.getxCo();		
		if(y>= 300 && y<=360 ){
			for(int i = 0; i < xCo.size(); i++){
				if(x >= xCo.get(i) && x <= (xCo.get(i)+60)){
					if(arrayQueue.predictRemove(i)){
						removed = arrayQueue.dequeue();
						wasRemoved = true;
						wasNotRemoved = false;
					}
					else{
						wasNotRemoved = true;
					}
				}
			}
		}

		paint = true;
		
	}

	private void arrayStackRemovePredict(int x, int y) {
		ArrayList<Integer> yCo = arrayStack.getYCo();
		
		if(x>= 400 && x<=460 ){
			for(int i = 0; i < yCo.size(); i++){
				if(y >= yCo.get(i) && y <= (yCo.get(i)+60)){
					if(arrayStack.predictRemove(i)){
						removed = arrayStack.pop();
						wasRemoved = true;
						wasNotRemoved = false;
					}	
					else{
						wasNotRemoved = true;
					}
				}
			}
		}	

		paint = true;		
	}

	private void arrayQueueAddPredict(int x, int y) {
		wasAdded = false;
		ArrayList<Integer> xCo = arrayQueue.getxCo();		
		if(y>= 300 && y<=360 ){
			for(int i = 0; i < xCo.size(); i++){
				if(x >= xCo.get(i) && x <= (xCo.get(i)+60)){
					if(arrayQueue.predictAdd(i)){
						arrayQueue.enqueue(input);
						wasAdded=true;
						wasNotAdded= false;
					}	
					else{
						wasNotAdded=true;
					}
				}
			}
		}	
		paint = true;	
	}

	private void arrayStackAddPredict(int x, int y) {
		wasAdded = false;
		ArrayList<Integer> yCo = arrayStack.getYCo();
		//Checks to see if mouse click is in range of x-coordinates of the stack
		if(x>= 400 && x<=460 ){
			for(int i = 0; i < yCo.size(); i++){
				//Checks if y-co is in range with i 
				if(y >= yCo.get(i) && y <= (yCo.get(i)+60)){
					System.out.println("YCO: " + yCo.get(i));
					if(arrayStack.predictAdd(i)){
						System.out.println("PREDICTION WAS CORRECT");
						arrayStack.push(input);	
						wasAdded=true;
						wasNotAdded= false;
					}	
					else{
						wasNotAdded=true;
					}
				}
			}
		}			
		paint = true;
		
	}

	private void queueAddPredict(int x, int y) {
		wasAdded = false;
		ArrayList<Integer> xCo = queue.getxCo();		
		if(y>= 300 && y<=360 ){
			for(int i = 0; i < xCo.size(); i++){
				if(x >= xCo.get(i) && x <= (xCo.get(i)+60)){
					if(queue.predictAdd(i)){
						queue.enqueue(input);
						wasAdded=true;
						wasNotAdded= false;
					}	
					else{
						wasNotAdded=true;
					}
				}
			}
		}	
		paint = true;
	}

	private void stackAddPredict(int x, int y) {
		wasAdded = false;
		ArrayList<Integer> yCo = stack.getYCo();
		//Checks to see if mouse click is in range of x-coordinates of the stack
		if(x>= 400 && x<=460 ){
			for(int i = 0; i < yCo.size(); i++){
				//Checks if y-co is in range with i 
				if(y >= yCo.get(i) && y <= (yCo.get(i)+60)){
					if(stack.predictAdd(i)){
						stack.push(input);	
						wasAdded=true;
						wasNotAdded= false;
					}	
					else{
						wasNotAdded=true;
					}
				}
			}
		}			
		paint = true;
	}

	public void stackRemovePredict(int x, int y){
		
		ArrayList<Integer> yCo = stack.getYCo();
		
		if(x>= 400 && x<=460 ){
			for(int i = 0; i < yCo.size(); i++){
				if(y >= yCo.get(i) && y <= (yCo.get(i)+60)){
					if(stack.predictRemove(i)){
						removed = stack.pop();
						wasRemoved = true;
						wasNotRemoved = false;
					}	
					else{
						wasNotRemoved = true;
					}
				}
			}
		}	

		paint = true;	
	}
		
	public void queueRemovePredict(int x, int y){

		ArrayList<Integer> xCo = queue.getxCo();		
		if(y>= 300 && y<=360 ){
			for(int i = 0; i < xCo.size(); i++){
				if(x >= xCo.get(i) && x <= (xCo.get(i)+60)){
					if(queue.predictRemove(i)){
						removed = queue.dequeue();
						wasRemoved = true;
						wasNotRemoved = false;
					}
					else{
						wasNotRemoved = true;
					}
				}
			}
		}

		paint = true;	
	}

	public void setPaint(boolean b) {
		// TODO Auto-generated method stub
		paint = b;
	}

	public boolean wasRemoved() {
		return wasRemoved;
	}
	public void setRemoved(boolean b){
		
		wasRemoved = b;
	}
	public boolean wasNotRemoved(){
		return wasNotRemoved;
	}
	public void setNotRemoved(boolean b){
		wasNotRemoved = b;
	}
	
	public boolean getWasAdded(){
		return wasAdded;
	}
	public boolean getWasNotAdded(){
		return wasNotAdded;
	}
	public void setWasAdded(boolean b){
		wasAdded = b;
	}
	
}


